<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\Plugin\ContactStage\Logic;

use Hyperf\Di\Annotation\Inject;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\WorkContact\Constants\AddWay;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Contract\WorkContactTagContract;
use MoChat\App\WorkContact\Contract\WorkContactTagPivotContract;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeDepartmentContract;
use MoChat\Plugin\ContactStage\Contract\ContactStageContract;
use MoChat\Plugin\ContactStage\Contract\ContactStageEmployeeContract;

/**
 * 客户阶段管理-列表.
 *
 * Class IndexLogic
 */
class IndexLogic
{
    /**
     * @Inject
     * @var WorkEmployeeDepartmentContract
     */
    protected $workEmployeeDepartmentService;

    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    /**
     * @Inject
     * @var ContactStageContract
     */
    protected $contactStageService;

    /**
     * 客户表.
     * @Inject
     * @var WorkContactContract
     */
    private $workContactService;

    /**
     * 员工 - 客户关联.
     * @Inject
     * @var WorkContactEmployeeContract
     */
    private $workContactEmployeeService;

    /**
     * 客户 - 阶段关联.
     * @Inject
     * @var ContactStageEmployeeContract
     */
    private $contactStageEmployeeService;

    /**
     * 标签.
     * @Inject
     * @var WorkContactTagContract
     */
    private $workContactTagService;

    /**
     * 客户 - 标签关联.
     * @Inject
     * @var WorkContactTagPivotContract
     */
    private $workContactTagPivotService;

    /**
     * 员工.
     * @Inject
     * @var WorkEmployeeContract
     */
    private $workEmployeeService;

    /**
     * 企业表.
     * @Inject
     * @var CorpContract
     */
    private $corpService;

    /**
     * 参数.
     * @var array
     */
    private $params;

    /**
     * 参数.
     * @var array
     */
    private $result;

    /**
     * @param array $params 请求参数
     * @return array 响应数组
     */
    public function handle(array $params): array
    {
        $this->params = $params;
        $this->result = [
            'page' => [
                'perPage' => 20,
                'total' => 0,
                'totalPage' => 0,
            ],
            'list' => [],
        ];

        // 处理查询条件
        $where = $this->handleWhere($this->params);

        // 标明没有数据
        if (empty($where)) {
            return $this->result;
        }

        return $this->getContactEmployeeInfo($where);
    }

    /**
     * 处理客户列表查询条件.
     */
    protected function handleWhere(array $params): array
    {
        $where = [];
        // 企业id
        $where['corpId'] = user()['corpIds'][0];

        // 添加时间搜索
        if (! empty($params['startTime'])) {
            $where['startTime'] = $params['startTime'];
        }
        if (! empty($params['endTime'])) {
            $where['endTime'] = $params['endTime'];
        }

        // 跟进时间搜索
        if (! empty($params['followStartTime'])) {
            $where['followStartTime'] = $params['followStartTime'];
        }
        if (! empty($params['followEndTime'])) {
            $where['followEndTime'] = $params['followEndTime'];
        }

        if (! empty($params['name'])) {
            $contacts = $this->workContactService->getWorkContactsByNameAlias($params['name'], user()['corpIds'][0], ['id'], 999);
            if (empty($contacts)) {
                return [];
            }
            $contactIds = array_column($contacts, 'id');
            $where['contactId'] = $contactIds;
        }

        // 所属客户搜索
        if ($params['employeeId'] > 0) {
            $where['employeeId'] = $params['employeeId'];
        }
        // 客户阶段搜索
        $allContactStage = $this->contactStageEmployeeService->getContactStageEmployeeByCorpId(user()['corpIds'][0]);
        $allIds = [];
        foreach ($allContactStage as $item) {
            $contactEmployee = $this->workContactEmployeeService->getWorkContactEmployeesByContactIdEmployeeIds($item['contactId'], [$item['employeeId']], ['id']);
            ! empty($contactEmployee) && $allIds[] = $contactEmployee['id'];
        }
        ! empty($allIds) && $where['ids'] = array_unique($allIds);
        if ($params['stageId'] > 0) {
            $contactStage = $this->contactStageEmployeeService->getContactStageEmployeeByStageId($params['stageId'], ['contact_id', 'employee_id']);
            if (empty($contactStage)) {
                return [];
            }
            $ids = [];
            foreach ($contactStage as $item) {
                $contactEmployee = $this->workContactEmployeeService->getWorkContactEmployeesByContactIdEmployeeIds($item['contactId'], [$item['employeeId']], ['id']);
                ! empty($contactEmployee) && $ids[] = $contactEmployee['id'];
            }
            ! empty($ids) && $where['ids'] = array_unique($ids);
        }

        return $where;
    }

    /**
     * 获取客户列表.
     * @param $where
     */
    private function getContactEmployeeInfo($where): array
    {
        $columns = [
            'id',
            'employee_id',
            'contact_id',
            'remark',
            'create_time',
            'add_way',
            'last_message_time',
            'status',
        ];
        $where['isFlag'] = 1;
        // 查询数据
        $list = $this->workContactEmployeeService->getWorkContactEmployeeIndex(
            $where,
            $columns,
            (int) $this->params['perPage'],
            (int) $this->params['page']
        );

        if (empty($list['data'])) {
            return $this->result;
        }

        // 客户id
        $contactIds = array_unique(array_column($list['data'], 'contactId'));
        // 员工id
        $employeeIds = array_unique(array_column($list['data'], 'employeeId'));
        // 查询客户基础信息
        $contact = $this->getContactInfo($contactIds);
        // 查询客户归属成员信息
        $employee = $this->getEmployee($employeeIds);

        foreach ($list['data'] as &$raw) {
            $raw['addWayText'] = AddWay::$Enum[$raw['addWay']] ?? '';
            $raw['name'] = '';
            $raw['avatar'] = '';
            $raw['stage'] = '';
            if (isset($contact[$raw['contactId']])) {
                $raw['businessNo'] = $contact[$raw['contactId']]['businessNo'];
                $raw['name'] = $contact[$raw['contactId']]['name'];
                $raw['avatar'] = $contact[$raw['contactId']]['avatar'] ? file_full_url($contact[$raw['contactId']]['avatar']) : $contact[$raw['contactId']]['avatar'];
            }

            $raw['employeeName'] = [];
            if (isset($employee[$raw['employeeId']])) {
                $raw['employeeName'] = $employee[$raw['employeeId']]['name'];
            }

            // 查询客户标签
            $raw['tag'] = $this->getContactTag($raw['contactId'], $raw['employeeId']);

            // 获取用户阶段
            $stage = $this->getContactStage($raw['contactId'], $raw['employeeId'], user()['corpIds'][0]);
            if ($stage) {
                $raw['stage'] = $stage['name'];
            }
        }
        unset($raw);

        // 返回数据
        $data = [
            'page' => [
                'perPage' => $list['per_page'] ?? 20,
                'total' => $list['total'] ?? 0,
                'totalPage' => $list['last_page'] ?? 0,
            ],
            'list' => empty($list['data']) ? [] : $list['data'],
        ];

        return $data;
    }

    /**
     * 获取客户信息.
     * @param $contactIds
     */
    private function getContactInfo($contactIds): array
    {
        $contact = $this->workContactService->getWorkContactsById($contactIds);
        if (! empty($contact)) {
            $contact = array_column($contact, null, 'id');
        }

        return $contact;
    }

    /**
     * 查询员工信息.
     * @param $employeeIds
     */
    private function getEmployee($employeeIds): array
    {
        // 根据员工id查询员工信息、企业id
        $employeeInfo = $this->workEmployeeService->getWorkEmployeesById($employeeIds, ['id', 'name', 'corp_id']);

        if (empty($employeeInfo)) {
            return [];
        }

        $corpIds = array_unique(array_column($employeeInfo, 'corpId'));

        // 查询企业名称
        $corpInfo = $this->corpService->getCorpsById($corpIds, ['id', 'name']);
        if (empty($corpInfo)) {
            return [];
        }
        $corpInfo = array_column($corpInfo, null, 'id');

        foreach ($employeeInfo as &$raw) {
            $raw['corpName'] = '';

            if (isset($corpInfo[$raw['corpId']])) {
                $raw['corpName'] = $corpInfo[$raw['corpId']]['name'];
            }
        }

        unset($raw);

        $employeeInfo = array_column($employeeInfo, null, 'id');

        return $employeeInfo;
    }

    /**
     * 获取客户标签.
     * @param $contactId
     * @param $employeeId
     */
    private function getContactTag($contactId, $employeeId): array
    {
        $contactTag = $this->workContactTagPivotService->getWorkContactTagPivotsByOtherId($contactId, $employeeId);
        if (empty($contactTag)) {
            return [];
        }

        $tagIds = array_unique(array_column($contactTag, 'contactTagId'));
        // 根据标签id查询标签名称
        $tagInfo = $this->workContactTagService->getWorkContactTagsById($tagIds, ['id', 'name']);

        if (empty($tagInfo)) {
            return [];
        }

        $tagInfo = array_column($tagInfo, null, 'id');

        $tagName = [];
        foreach ($contactTag as &$raw) {
            if (isset($tagInfo[$raw['contactTagId']])) {
                $tagName[] = $tagInfo[$raw['contactTagId']]['name'];
            }
        }
        unset($raw);

        return array_merge(array_unique($tagName));
    }

    /**
     * 获取客户标签.
     * @param $contactId
     * @param $employeeId
     * @param $corpId
     */
    private function getContactStage($contactId, $employeeId, $corpId): array
    {
        $stage = $this->contactStageEmployeeService->getContactStageEmployeeByOtherId($contactId, $employeeId, $corpId, ['stage_id']);
        if (! $stage) {
            return [];
        }

        return $this->contactStageService->getContactStageById($stage['stageId']);
    }
}
